#include "NcSyncFile.h"
#include "NcDimTime.h"

namespace OCPP
{
	using namespace Volume;
	NcSyncFile::NcSyncFileInstances NcSyncFile::instances;
	std::mutex NcSyncFile::intanceMutex;

	std::shared_ptr<NcDimWrapper> NcSyncFile::getCacheVar(String name, const VolumeOptions& options)
	{
		NcVar var = ncFile.getVar(name);
		if (var.isNull()) return std::make_shared<NcDimWrapper>(name);

		{
			CORE_LOCK_RW_MUTEX_READ(rw_mutex);
			auto it = _dimWrapperCaches.find(name);
			if (it != _dimWrapperCaches.end()) {
				return it->second;
			}
		}

		std::shared_ptr<NcDimWrapper> dimWrapper;

		CORE_LOCK_RW_MUTEX_WRITE(rw_mutex);

		if (NcUtil::isDimT(name, options))
		{
			IntVector iv = readInt(var);
			auto dim = std::make_shared<NcDimTime>(name, std::move(iv));
			dim->setTimeUnit(var);
			dimWrapper = dim;
		}
		else
		{
			FloatVector fv = readFloat(var);
			dimWrapper = std::make_shared<NcDimWrapper>(name, std::move(fv));
		}

		_dimWrapperCaches[name] = dimWrapper;

		return dimWrapper;
	}

	FloatVector NcSyncFile::readFloat(NcVar var)
	{
		CORE_LOCK_MUTEX(mutex);
		return NcUtil::readFloat(var);
	}

	FloatVector NcSyncFile::readFloat(NcVar var, NcReadIndex index)
	{
		const auto& [ori, shp] = index;
		CORE_LOCK_MUTEX(mutex);
		FloatVector fv;
		size_t size = 1;
		for (auto i : shp) size *= i;
		try
		{
			fv.resize(size);
			var.getVar(ori, shp, &fv[0]);

			auto attrs = var.getAtts();

			if (attrs.find("scale_factor") != attrs.end()
				&& attrs.find("add_offset") != attrs.end())
			{
				auto attr1 = var.getAtt("scale_factor");
				auto attr2 = var.getAtt("add_offset");

				float scale = NcUtil::readFloatAttr(attr1, 1.0f);
				float offset = NcUtil::readFloatAttr(attr2, 0.0f);

				if (scale != 1.0f || offset != 0.0f)
				{
					for (auto& value : fv)
					{
						value *= scale;
						value += offset;
					}
				}
			}
		}
		catch (exceptions::NcException& e) {
			OCPP_LOG_ERROR << e.what() << "\n";
		}
		return fv;
	}

	IntVector NcSyncFile::readInt(NcVar var)
	{
		CORE_LOCK_MUTEX(mutex);
		return NcUtil::readInt(var);
	}
}


